/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
**     of its contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QImage>
#include <QList>
#include <QDebug>
#include <QApplication>
#include <QtConcurrentMap>
#include "thread/jthread.h"
#include "jconcurrentinc.h"
#include "thread/jfuturewatcher.h"
#include <QtGui>

QImage scale(const QImage &image)
{
    qDebug() << "Scaling image in thread" << QThread::currentThread();
    return image.scaled(QSize(100, 100), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}

class Thread : public JThread
{
public:
    virtual void run()
    {
        //JMutex mutex;
        while (true) {
            //JMutexLocker locker(mutex);
            qDebug() << "test";
            sleep(1);
        }
    }
};

void my_func()
{
    qDebug() << "my_func";
}

class Future : public QObject, public JFutureWatcherBaseSignal
{
public:
    Future(QObject *parent = NULL);
    ~Future();

private:
    void run_thread();

private:
    JFuture<void> *future;
    JFutureWatcher<void> *watcher;

    // JFutureWatcherBaseSignal interface
public:
    void started()
    {
        qDebug() << "started thread";
    }
    virtual void finished()
    {
        qDebug() << "finshed thread";
    }
    void canceled()
    {
        qDebug() << "canceled thread";
    }
    void paused()
    {
        qDebug() << "paused thread";
    }
    void resumed()
    {
        qDebug() << "resumed thread";
    }
    void resultReadyAt(int resultIndex)
    {
        J_UNUSED(resultIndex);
        qDebug() << "resultReadyAt thread";
    }
    void resultsReadyAt(int beginIndex, int endIndex)
    {
        J_UNUSED(beginIndex);
        J_UNUSED(endIndex);
        qDebug() << "resultsReadyAt thread";
    }
    void progressRangeChanged(int minimum, int maximum)
    {
        J_UNUSED(minimum);
        J_UNUSED(maximum);
        qDebug() << "progressRangeChanged thread";
    }
    void progressValueChanged(int progressValue)
    {
        J_UNUSED(progressValue);
        qDebug() << "progressValueChanged thread";
    }
    void progressTextChanged(const std::string &progressText)
    {
        J_UNUSED(progressText);
        qDebug() << "progressTextChanged thread";
    }
};

Future::Future(QObject *parent)
    : QObject(parent)
{
    future = new JFuture<void>;
    watcher = new JFutureWatcher<void>;
    watcher->setListener(this);
    run_thread();
    qDebug() << "now here";
}

Future::~Future()
{
}

void Future::run_thread()
{
    *future = JConcurrent::run(my_func);
    watcher->setFuture(*future);
}

#include <QRunnable>

class runnableInst : public JRunnable
{
public:
    runnableInst(QProgressBar* progressBar);
    virtual ~runnableInst();

    void run();

private:
    QProgressBar* m_ProgressBar;
};

runnableInst::runnableInst(QProgressBar* progressBar)
    : JRunnable(), m_ProgressBar(progressBar)
{
}

runnableInst::~runnableInst()
{

}

void runnableInst::run()
{
    for(int step = 1; step <= 100; step++)
    {
        QMetaObject::invokeMethod(m_ProgressBar, "setValue", Q_ARG(int, step));
    }
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
#if 1
    const int imageCount = 20;

    // Create a list containing imageCount images.
    jlist<QImage> images;
    for (int i = 0; i < imageCount; ++i)
        images.push_back(QImage(1600, 1200, QImage::Format_ARGB32_Premultiplied));

    // Use QtConcurrentBlocking::mapped to apply the scale function to all the
    // images in the list.
   jlist<QImage> thumbnails = JConcurrent::blockingMapped<jlist<QImage> >(images, scale);
    //QList<QImage> thumbnails = QtConcurrent::blockingMapped<QList<QImage> >(images, scale);

    //Future future;
#else
    QProgressBar progressBar;
    progressBar.setValue(50);
    progressBar.show();

    runnableInst* hInst = new runnableInst(&progressBar);
    QThreadPool::globalInstance()->start(reinterpret_cast<QRunnable *>(hInst));
#endif
    return app.exec();
}

